package jkCore.nativeNotification;

import static android.content.Context.JOB_SCHEDULER_SERVICE;

import static org.cocos2dx.lib.Cocos2dxHelper.getPackageName;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.PermissionChecker;

import com.google.gson.Gson;
import com.puzzlegames.jigsaw.puzzles.free.R;

import org.cocos2dx.javascript.AppActivity;
import org.cocos2dx.javascript.service.SDKClass;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import jkCore.utils.AlarmTimer;

public class NativeNotification extends SDKClass {
    private static final long SCHEDULE_PERIOD = 15 * 60 * 1000;
    private static String TAG = "NativeNotification";
    private static NativeNotification instance;
    private static Context mContext;
    private Activity mActivity;
    private SharedPreferences mSharedPreferences;
    public static String Notify_Action = "Notify_Action";
    // 需要的权限集
    private boolean requestingPermission = false;
    private SparseArray<Integer> permissionCodes = new SparseArray<Integer>();
    private int permissionRequestTag;
    private int permissionRequestCnt;
    public final String[] NOTIFICATION_PERMISSIONS = {
//            Manifest.permission.ACCESS_NOTIFICATION_POLICY
    };
    public final int NOTIFICATION_PERMISSIONS_RESULT_CODE = 1;
    private PermissionsListener mNotificationPermissionsListener;

    public interface PermissionsListener {
        void onCallBack(Context context);
    }

    @Override
    public void init(Context context) {
        Log.d(TAG, "init ");

        instance = this;
        mContext = context;
        mActivity = (AppActivity) mContext;
//        checkAndRequestPermission(NOTIFICATION_PERMISSIONS_RESULT_CODE);

        mSharedPreferences = mContext.getSharedPreferences("SHARE_PREFERENCE_NOTIFICATION", Context.MODE_PRIVATE);
        if (!isNotificationEnabled() && mSharedPreferences.getString("JKNotice_0", "") == "") {
            showPermissionsDialog(NOTIFICATION_PERMISSIONS_RESULT_CODE);
        }
    }

    @Override
    public void setGLSurfaceView(GLSurfaceView view) {

    }

    @Override
    public void onResume() {

    }

    @Override
    public void onPause() {

    }

    @Override
    public void onDestroy() {

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    }

    /**
     * 申请权限结果响应
     *
     * @param requestCode  权限集编号
     * @param permissions  权限集
     * @param grantResults 申请结果对象
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        Log.d(TAG, "onRequestPermissionsResult requestCode = " + requestCode);

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        switch (requestCode) {
            case NOTIFICATION_PERMISSIONS_RESULT_CODE:
                //权限请求失败
                if (grantResults.length == NOTIFICATION_PERMISSIONS.length) {
                    boolean allOK = true;
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            //弹出对话框引导用户去设置
                            showPermissionsDialog(NOTIFICATION_PERMISSIONS_RESULT_CODE);
                            Toast.makeText(mContext, R.string.permission_denied, Toast.LENGTH_LONG).show();
                            allOK = false;

                            break;
                        }
                    }
                    if (allOK) {
                        mNotificationPermissionsListener.onCallBack(mActivity);
                    }
                } else {
//                    Toast.makeText(this, "已授权", Toast.LENGTH_LONG).show();
                    mNotificationPermissionsListener.onCallBack(mActivity);
                }
                permissionCodes.remove(NOTIFICATION_PERMISSIONS_RESULT_CODE);
                requestingPermission = false;
                permissionRequestCnt--;
                doOneRequestPermission();

                break;

            default:
                break;
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
    }

    @Override
    public void onRestart() {

    }

    @Override
    public void onStop() {

    }

    @Override
    public void onBackPressed() {

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {

    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

    }

    @Override
    public void onStart() {

    }

// ============================================================================================
// =====================================   内部方法   ===========================================
// ============================================================================================

    // 权限检测并请求
    private Boolean checkAndRequestPermission(int resultCode) {
        Log.d(TAG, "checkAndRequestAuthPermission");

        ArrayList<String> lackedPermissions = new ArrayList<String>(NOTIFICATION_PERMISSIONS.length);
        for (int i = 0; i < NOTIFICATION_PERMISSIONS.length; i++) {
            int result = PermissionChecker.checkCallingOrSelfPermission(mContext, NOTIFICATION_PERMISSIONS[i]);
            if (result != PackageManager.PERMISSION_GRANTED) {
                lackedPermissions.add(NOTIFICATION_PERMISSIONS[i]);
            }
        }

        Log.d(TAG, "checkAndRequestAuthPermission lackedPermissions.size() = " + lackedPermissions.size());
        if (lackedPermissions.size() > 0) {
            String[] rP = new String[lackedPermissions.size()];
            lackedPermissions.toArray(rP);
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M - 1) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mActivity.requestPermissions(rP, resultCode);
                }
            } else {
                int[] grantResults = new int[rP.length];
                for (int i = 0; i < grantResults.length; i++) {
                    grantResults[i] = PackageManager.PERMISSION_GRANTED;
                }
                onRequestPermissionsResult(resultCode, rP, grantResults);
                Log.e(TAG, "The platform api version below 23 M, can not request permissions!");
            }

            return false;
        } else {
        }

        return true;
    }

    /**
     * 申请权限
     *
     * @param resultCode 权限集编号
     * @param listener   回调
     */
    public void requestPermission(int resultCode, @Nullable PermissionsListener listener) {
        Log.d(TAG, "requestPermission resultCode = " + resultCode);

        String[] permissions = null;
        switch (resultCode) {
            case NOTIFICATION_PERMISSIONS_RESULT_CODE:
                mNotificationPermissionsListener = listener;
                permissions = NOTIFICATION_PERMISSIONS;

                break;

            default:
                break;
        }
        if (permissions != null) {
            boolean needRequest = false;
            for (int i = 0; i < permissions.length; i++) {
                String permission = permissions[i];
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (mActivity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                        needRequest = true;
                    }
                } else {
                    if (PermissionChecker.checkSelfPermission(mContext, permission) != PermissionChecker.PERMISSION_GRANTED) {
                        needRequest = true;
                    }
                }
            }
            if (needRequest) {
                permissionCodes.put(permissionRequestTag++, resultCode);
                permissionRequestCnt++;
                if (!requestingPermission) {
                    doOneRequestPermission();
                }
            } else {
                listener.onCallBack(mActivity);
            }
        }
    }

    public void doOneRequestPermission() {
        Log.d(TAG, "doOneRequestPermission permissionRequestCnt = " + permissionRequestCnt);

        if (permissionRequestCnt > 0) {
            int permissionCode = 0;
            for (int i = 0; i < permissionCodes.size(); i++) {
                int key = permissionCodes.keyAt(i);
                permissionCode = permissionCodes.get(key);
                if (permissionCode > 0) {
                    break;
                }
            }
            switch (permissionCode) {
                case NOTIFICATION_PERMISSIONS_RESULT_CODE:
                    // 当API大于 23 时，才动态申请权限
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        requestingPermission = true;
                        mActivity.requestPermissions(NOTIFICATION_PERMISSIONS, NOTIFICATION_PERMISSIONS_RESULT_CODE);
                    }

                    break;

                default:
                    if (!isNotificationEnabled()) {
                        goToNotificationSetting();
                    }

                    break;
            }
        }
    }

    /**
     * 弹出权限不完整的提示框
     *
     * @param resultCode 权限集编号
     */
    private void showPermissionsDialog(final int resultCode) {
        String msg = "";
        switch (resultCode) {
            case NOTIFICATION_PERMISSIONS_RESULT_CODE:
                msg = mContext.getResources().getString(R.string.need_notification_permissions);

                break;

            default:
//                msg = mContext.getResources().getString(R.string.need_permissions);

                break;
        }
        if (msg != "") {
            AlertDialog dialog = new AlertDialog.Builder(mContext)
                    .setMessage(msg)
                    .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            goToAppSetting(resultCode);
                        }
                    })
                    .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    })
                    .setCancelable(false)
                    .show();
        }
    }

    /**
     * 跳转到设置界面
     *
     * @param resultCode 权限集编号
     */
    private void goToAppSetting(int resultCode) {
        Log.d(TAG, "goToAppSetting");

        Intent intent = new Intent();
        switch (resultCode) {
            case NOTIFICATION_PERMISSIONS_RESULT_CODE:
                if (!isNotificationEnabled()) {
                    goToNotificationSetting();
                }

                break;

            default:
                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

                break;
        }
        intent.setData(Uri.fromParts("package", getPackageName(), null));
        mContext.startActivity(intent);
    }

    /**
     * 是否开启通知权限
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    private boolean isNotificationEnabled() {
        Log.d(TAG, "isNotificationEnabled");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ///< 8.0手机以上
            if (((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)).getImportance() == NotificationManager.IMPORTANCE_NONE) {
                return false;
            }
        }

        AppOpsManager mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        ApplicationInfo appInfo = mContext.getApplicationInfo();
        String pkg = mContext.getApplicationContext().getPackageName();
        int uid = appInfo.uid;

        Class appOpsClass = null;
        try {
            appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE,
                    String.class);
            Field opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION");

            int value = (Integer) opPostNotificationValue.get(Integer.class);
            return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 跳到通知栏设置界面
     */
    private void goToNotificationSetting() {
        Intent localIntent = new Intent();
        ///< 直接跳转到应用通知设置的代码
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            localIntent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            localIntent.putExtra(Settings.EXTRA_APP_PACKAGE, mContext.getPackageName());
        } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
                android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            localIntent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
            localIntent.putExtra("app_package", mContext.getPackageName());
            localIntent.putExtra("app_uid", mContext.getApplicationInfo().uid);
        } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
            localIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            localIntent.addCategory(Intent.CATEGORY_DEFAULT);
            localIntent.setData(Uri.parse("package:" + mContext.getPackageName()));
        } else {
            ///< 4.4以下没有从app跳转到应用通知设置页面的Action，可考虑跳转到应用详情页面,
            localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (Build.VERSION.SDK_INT >= 9) {
                localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                localIntent.setData(Uri.fromParts("package", mContext.getPackageName(), null));
            } else if (Build.VERSION.SDK_INT <= 8) {
                localIntent.setAction(Intent.ACTION_VIEW);
                localIntent.setClassName("com.android.settings", "com.android.setting.InstalledAppDetails");
                localIntent.putExtra("com.android.settings.ApplicationPkgName", mContext.getPackageName());
            }
        }
        mContext.startActivity(localIntent);
    }

// ============================================================================================
// =====================================   外部方法   ===========================================
// ============================================================================================

// ============================================================================================
// =====================================   静态方法   ===========================================
// ============================================================================================

    /**
     * 推送通知
     *
     * @param id     id
     * @param title  标题
     * @param msg    内容
     * @param time   推送时间，时间戳
     * @param period 周期，毫秒，默认一天
     */
    public static void notify(String id, String title, String msg, String time, String period) {
        Log.d(TAG, "notify id = " + id + " title = " + title + " msg = " + msg + " time = " + time + " period = " + period);

//        time = String.valueOf(System.currentTimeMillis());
        NotifyData notifyData = new NotifyData();
        notifyData.id = Integer.parseInt(id);
        notifyData.title = title;
        notifyData.msg = msg;
        notifyData.time = Long.parseLong(time);
        notifyData.period = Long.parseLong(period);
        Gson gson = new Gson();
        String json = gson.toJson(notifyData);
        NativeNotification.instance.mSharedPreferences.edit().putString("JKNotice_" + id, json).apply();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            scheduleNotifications(notifyData.id, SCHEDULE_PERIOD, NativeNotification.instance.mContext);
        } else {
            AlarmTimer.setAlarmTimer(NativeNotification.mContext, notifyData.id, notifyData.time, Notify_Action, json);
        }
    }

    public static void scheduleNotifications(int id, long period, Context context) {
        Log.d(TAG, "scheduleNotifications");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            JobScheduler jobScheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
            JobInfo jobInfo = new JobInfo.Builder(id, new ComponentName(getPackageName(), NotificationService.class.getName()))
                    .setRequiresCharging(false)
                    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE) //不管是否有网络
                    .setRequiresDeviceIdle(false)
                    .setPersisted(true) //系统重启后保留job
//                    .setOverrideDeadline(60 * 1000)
//                    .setMinimumLatency(1 * 1000)
                    .setPeriodic(period)
                    .setBackoffCriteria(TimeUnit.MINUTES.toMillis(10), JobInfo.BACKOFF_POLICY_LINEAR)  //线性重试方案
                    .build();
            jobScheduler.cancel(id);
            jobScheduler.schedule(jobInfo);
        }
    }
}